package utils {
	/**
	 * ...
	 * @author jianping.shenjp
	 */
	import flash.display.Graphics;

	public class Triangle {
		private var pointA:Point3D;
		private var pointB:Point3D;
		private var pointC:Point3D;
		private var color:uint;
		public var light:Light;

		public function Triangle(a:Point3D, b:Point3D, c:Point3D, color:uint){
			pointA = a;
			pointB = b;
			pointC = c;
			this.color = color;
		}

		public function draw(g:Graphics):void {
			if (isBackFace()){
				return;
			}
			g.lineStyle(0, 0);
			if (light){
				g.beginFill(getAdjustedColor());
			} else {
				g.beginFill(color, 0.5);
			}
			g.moveTo(pointA.screenX, pointA.screenY);
			g.lineTo(pointB.screenX, pointB.screenY);
			g.lineTo(pointC.screenX, pointC.screenY);
			g.lineTo(pointA.screenX, pointA.screenY);
			g.endFill();
		}

		/**
		 * 如果是逆时针的方向(背面)则返回 true，如果顺时针(正面)则返回 false。
		 *
		 * 如果面向我们的多边形的点是顺时钟安排的，
		 * 那么当它们转而背对我们时它们都将是逆时针排列的。
		 * @return
		 */
		private function isBackFace():Boolean {
// 见 http://www.jurjans.lv/flash/shape.html
			var cax:Number = pointC.screenX - pointA.screenX;
			var cay:Number = pointC.screenY - pointA.screenY;
			var bcx:Number = pointB.screenX - pointC.screenX;
			var bcy:Number = pointB.screenY - pointC.screenY;
			return cax * bcy > cay * bcx;
		}

		/**
		 *  计算深度
		 */
		public function get depth():Number {
			var zpos:Number = Math.min(pointA.z, pointB.z);
			zpos = Math.min(zpos, pointC.z);
			return zpos;
		}

		/**
		 * 关于其灯光颜色、角度、亮度的函数
		 * @return
		 */
		public function getAdjustedColor():uint {
			var red:Number = color >> 16;
			var green:Number = color >> 8 & 0xff;
			var blue:Number = color & 0xff;
			var lightFactor:Number = getLightFactor();
			red *= lightFactor;
			green *= lightFactor;
			blue *= lightFactor;
			return red << 16 | green << 8 | blue;
		}

		private function getLightFactor():Number {
			//向量ab
			var ab:Object = new Object();
			ab.x = pointA.x - pointB.x;
			ab.y = pointA.y - pointB.y;
			ab.z = pointA.z - pointB.z;
			//向量bc
			var bc:Object = new Object();
			bc.x = pointB.x - pointC.x;
			bc.y = pointB.y - pointC.y;
			bc.z = pointB.z - pointC.z;
			//向量ab、bc的模
			var norm:Object = new Object();
			norm.x = (ab.y * bc.z) - (ab.z * bc.y);
			norm.y = -((ab.x * bc.z) - (ab.z * bc.x));
			norm.z = (ab.x * bc.y) - (ab.y * bc.x);
			//点积
			var dotProd:Number = norm.x * light.x + norm.y * light.y + norm.z * light.z;
			//法线的量值
			var normMag:Number = Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
			//灯光的量值
			var lightMag:Number = Math.sqrt(light.x * light.x + light.y * light.y + light.z * light.z);
			/**
			 * 其中 dotProd 是一个分量，而 normMag * lightMag 是另一个分量。两者相除得出一个比率。
			 * 回忆一下第三章，一个角度的余弦给了我们一个比率，
			 * 而一个比率的反余弦给了我们一个角度。这就是灯光照射在多边形表面上的角度。
			 * 它的范围在 0 到 Math.PI 个弧度之间（0 到180 度），也就是说灯光完全照射在物体前面上或完全照射在物体背面。
			 * 用这个数除以 Math.PI 得出一个百分数，再用它乘以 brightness 的百分比就得出了最终用于改变底色的滤光系数。
			 */
			//return Math.acos(dotProd / normMag * lightMag) / Math.PI * light.brightness;
			return (Math.acos(dotProd / (normMag * lightMag)) / Math.PI) * light.brightness;
		}
	}
}